home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xarchie-2.0.9
/
fchooser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-18
|
9KB
|
280 lines
/*
* fchooser.c : Xarchie interface to the FileChooser
*
* The FileChooser enforces very little policy. This wrapper adds
* the following:
* - The FileChooser is created with several other widgets: a Text
* widget, and OK button, and a cancel button. These are created in
* the sameparent, but other widgets can also be there.
* - Selecting a file in the FileChooser just puts the string in the
* Text widget. You have to hit Ok to use it.
* - When ok is clicked or Return typed, the directory from the fileChooser
* and the file from the Text are concatenated. If the result is a
* directory, the fileChooser is reset to that directory. Otherwise
* the callback is called with the filename as call_data.
* - Leading tildes are expanded in directories entered in the Text widget.
*
* Oh yeah, if FILECHOOSER is not defined, ignore all that about it. In that
* case we just have a Text and two buttons.
*
* George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
* 13 May 1993: Fixes for when FILECHOOSER not defined.
* 14 May 1993: More of the same (find MAXPATHLEN), initialize dir.
* 30 Jun 1993: Encore umax fixes from Gerry.Tomlinson@newcastle.ac.uk.
*
*/
#include "config.h"
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_ISDIR
# define S_ISDIR(m) (m & S_IFDIR) /* Encore umax */
#endif
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/keysym.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Command.h>
#ifdef FILECHOOSER
#include <FChooser.h>
#endif
#include "fchooser.h"
#include "xarchie.h"
#include "xutil.h"
#include "tilde.h"
#include "status.h"
#include "alert.h"
#include "debug.h"
/*
* Functions defined here:
*/
FileChooserInfo *createFileChooser(
#if NeedFunctionPrototypes
Widget shell,
Widget parent,
char *basename,
FileChooserOkProc okCallback,
FileChooserCancelProc cancelCallback,
XtPointer client_data
#endif
);
#ifdef FILECHOOSER
static void fileChooserCallback();
#endif
static void okButtonCallback(),cancelButtonCallback();
static void keyPressEventHandler(),nonmaskableEventHandler();
/* - - - - - - - - */
FileChooserInfo *
createFileChooser(shell,parent,basename,okCallback,cancelCallback,client_data)
Widget shell,parent;
char *basename;
FileChooserOkProc okCallback;
FileChooserCancelProc cancelCallback;
XtPointer client_data;
{
FileChooserInfo *info;
char name[64];
Arg args[1];
info = XtNew(FileChooserInfo);
info->shell = shell;
info->okCallback = okCallback;
info->cancelCallback = cancelCallback;
info->client_data = client_data;
#ifdef FILECHOOSER
status0("Initializing File Selector...");
sprintf(name,"%sFileChooser",basename);
info->fcw =
XtCreateManagedWidget(name,xfwfFileChooserWidgetClass,parent,NULL,0);
XtAddCallback(info->fcw,XtNcallback,fileChooserCallback,(XtPointer)info);
status0("Done.");
XtSetArg(args[0],XtNfromVert,info->fcw);
#else
XtSetArg(args[0],XtNfromVert,NULL);
#endif
sprintf(name,"%sTextLabel",basename);
(void)XtCreateManagedWidget(name,labelWidgetClass,parent,args,1);
sprintf(name,"%sText",basename);
info->text =
XtCreateManagedWidget(name,asciiTextWidgetClass,parent,args,1);
sprintf(name,"%sOkButton",basename);
info->okButton =
XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
XtAddCallback(info->okButton,XtNcallback,okButtonCallback,(XtPointer)info);
/* Allow Return in the Text to be Ok */
XtAddEventHandler(info->text,KeyPressMask,False,
keyPressEventHandler,(XtPointer)info);
sprintf(name,"%sCancelButton",basename);
info->cancelButton =
XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
XtAddCallback(info->cancelButton,XtNcallback,
cancelButtonCallback,(XtPointer)info);
/* Allow WM_DELETE_WINDOW to the Shell to be Cancel */
if (info->shell != NULL)
XtAddEventHandler(info->shell,NoEventMask,True,
nonmaskableEventHandler,(XtPointer)info);
return(info);
}
#ifdef FILECHOOSER
/*
* When a selection is made, put the string in the Text item. If background
* selected, clear the Text item.
*/
/*ARGSUSED*/
static void
fileChooserCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* info */
XtPointer call_data; /* return struct */
{
FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
XfwfFileChooserReturnStruct *ret =
(XfwfFileChooserReturnStruct *)call_data;
Arg args[1];
DEBUG1("fileChooserCallback: fcinfo=0x%lx\n",fcinfo);
if (fcinfo == NULL || fcinfo->text == NULL) /* creating */
return;
if (ret->file == NULL) {
XtSetArg(args[0],XtNstring,"");
} else {
XtSetArg(args[0],XtNstring,ret->file);
}
XtSetValues(fcinfo->text,args,1);
DEBUG0("fileChooserCallback: done\n");
}
#endif /* FILECHOOSER */
/*
* If Ok is clicked, get the directory from the FileChooser (if FILECHOOSER)
* and get the filename from the Text. Do tilde expansion. If result is
* a directory, use it in the FileChooser, otherwise invoke the callback
* passing filename and client_data. Finally free the info.
*/
/*ARGSUSED*/
static void
okButtonCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* info */
XtPointer call_data; /* not used */
{
FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
static char filename[MAXPATHLEN];
struct stat statbuf;
char *dir,*file;
DEBUG1("okButtonCallback: fcinfo=0x%lx\n",fcinfo);
filename[0] = '\0';
#ifdef FILECHOOSER
dir = XfwfFileChooserCurrentDirectory((XfwfFileChooserWidget)(fcinfo->fcw));
DEBUG1("okButtonCallback: dir=\"%s\"\n",dir);
#else
dir = "";
#endif
file = getWidgetString(fcinfo->text);
if (file == NULL || *file == '\0') {
alert0("No filename specified!");
return;
}
DEBUG1("okButtonCallback: file=\"%s\"\n",file);
if (*file == '/') { /* absolute path */
strcpy(filename,file);
} else if (*file == '~') { /* tilde path */
strcpy(filename,tildeExpand(file));
} else { /* relative to fcw */
sprintf(filename,"%s%s",dir,file);
}
DEBUG1("okButtonCallback: filename=\"%s\"\n",filename);
#ifdef FILECHOOSER
/* If we got a directory, go open it rather than use it */
if (stat(filename,&statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
XfwfFileChooserChangeDirectory((XfwfFileChooserWidget)fcinfo->fcw,
filename);
return;
}
#endif
if (fcinfo->okCallback != NULL) {
DEBUG0("okButtonCallback: calling okCallback...\n");
(*(fcinfo->okCallback))(fcinfo,filename,fcinfo->client_data);
}
DEBUG0("okButtonCallback: done\n");
}
/*
* If Cancel is clicked, invoke the callback passing client_data.
* Finally free the info.
*/
/*ARGSUSED*/
static void
cancelButtonCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* fcinfo */
XtPointer call_data; /* not used */
{
FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
DEBUG1("cancelButtonCallback: fcinfo=0x%lx\n",fcinfo);
if (fcinfo->cancelCallback != NULL) {
DEBUG0("cancelButtonCallback: calling cancelCallback\n");
(*(fcinfo->cancelCallback))(fcinfo,fcinfo->client_data);
}
DEBUG0("cancelButtonCallback: done\n");
}
/*
* KeyPress event handler for Text item: When Return is typed, act as if
* OK had been clicked. If this event isn't Return, just let it be
* dispatched normally.
*/
/*ARGSUSED*/
static void
keyPressEventHandler(w,client_data,event,continue_to_dispatch)
Widget w;
XtPointer client_data;
XEvent *event;
Boolean *continue_to_dispatch;
{
KeySym keysym;
char str[8];
DEBUG1("keyPressHandler: w=0x%x\n",w);
(void)XLookupString((XKeyEvent*)event,str,sizeof(str),&keysym,NULL);
if (keysym == XK_Return) {
DEBUG0("keyPressHandler: calling okButtonCallback...\n");
okButtonCallback(NULL,client_data,NULL);
}
DEBUG0("keyPressHandler: done\n");
}
/*
* Nonmaskable event handler for Shell: If the event is a ClientMessage
* of WM_PROTOCOLS then act as if Cancel had been clicked.
*/
/*ARGSUSED*/
static void
nonmaskableEventHandler(w,client_data,event,continue_to_dispatch)
Widget w;
XtPointer client_data;
XEvent *event;
Boolean *continue_to_dispatch;
{
DEBUG1("nonmaskableHandler: w=0x%x\n",w);
if (event->type == ClientMessage &&
event->xclient.data.l[0] == WM_DELETE_WINDOW) {
DEBUG0("nonmaskableHandler: calling cancelButtonCallback\n");
cancelButtonCallback(NULL,client_data,NULL);
}
DEBUG0("nonmaskableHandler: done\n");
}